home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Complementary Applications 2004 February / SGI IRIX 6.5 Complementary Applications 2004 February.iso / dist / cde.idb / usr / dt / share / examples / dtdnd / icon.c.z / icon.c
Encoding:
C/C++ Source or Header  |  2003-11-18  |  15.5 KB  |  563 lines

  1. /*
  2.  * icon.c
  3.  *
  4.  * Copyright 2000, Silicon Graphics, Inc.
  5.  * ALL RIGHTS RESERVED
  6.  * 
  7.  * UNPUBLISHED -- Rights reserved under the copyright laws of the United
  8.  * States.   Use of a copyright notice is precautionary only and does not
  9.  * imply publication or disclosure.
  10.  *
  11.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
  12.  * Use, duplication or disclosure by the Government is subject to restrictions
  13.  * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
  14.  * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
  15.  * in similar or successor clauses in the FAR, or the DOD or NASA FAR
  16.  * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
  17.  * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
  18.  *
  19.  * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
  20.  * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
  21.  * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
  22.  * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
  23.  * GRAPHICS, INC.
  24.  */
  25. /* $XConsortium: icon.c /main/cde1_maint/1 1995/07/17 16:43:09 drk $ */
  26. /*****************************************************************************
  27.  *****************************************************************************
  28.  **
  29.  **   File:         icon.c
  30.  **
  31.  **   Description:  Icon support functions for the CDE Drag & Drop Demo.
  32.  **
  33.  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
  34.  **  (c) Copyright 1993, 1994 International Business Machines Corp.
  35.  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  36.  **  (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
  37.  **      Novell, Inc.
  38.  **
  39.  ****************************************************************************
  40.  ************************************<+>*************************************/
  41.  
  42. #include <stdio.h>
  43.  
  44. #include <Xm/Screen.h>
  45.  
  46. #include <Dt/Dts.h>
  47. #include <Dt/Dnd.h>
  48.  
  49. #include "icon.h"
  50.  
  51.  /*************************************************************************
  52.  *
  53.  *       Data Structures & Private Declarations For Icon Handling Functions
  54.  *
  55.  **************************************************************************/
  56.  
  57. #define ICON_TEXT_YGAP  2
  58.  
  59. #define ICON_PATH               "/usr/dt/appconfig/icons/C"
  60. #define ICON_BITMAP_SUFFIX      "m.bm"
  61. #define ICON_MASK_SUFFIX        "m_m.bm"
  62.  
  63. /*
  64.  * Default Generic Icon Bitmap & Mask
  65.  */
  66.  
  67. #define iconWidth 32
  68. #define iconHeight 32
  69. static unsigned char iconBits[] = {
  70.    0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x08, 0x00, 0x00, 0x08,
  71.    0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0x9d, 0x6d, 0x08,
  72.    0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0xf9, 0xed, 0x08,
  73.    0x08, 0x00, 0x00, 0x08, 0xc8, 0x6e, 0x7d, 0x08, 0x08, 0x00, 0x00, 0x08,
  74.    0xc8, 0x9d, 0xef, 0x09, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xdd, 0xb3, 0x08,
  75.    0x08, 0x00, 0x00, 0x08, 0xc8, 0xdf, 0xfd, 0x09, 0x08, 0x00, 0x00, 0x08,
  76.    0xc8, 0xf6, 0xde, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08,
  77.    0x88, 0xed, 0xd2, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xbb, 0xf3, 0x08,
  78.    0x08, 0x00, 0x00, 0x08, 0x48, 0xdf, 0x5e, 0x08, 0x08, 0x00, 0x00, 0x08,
  79.    0xc8, 0x36, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08,
  80.    0x08, 0x00, 0x00, 0x08, 0xf8, 0xff, 0xff, 0x0f};
  81.  
  82. #define iconMaskWidth 32
  83. #define iconMaskHeight 32
  84. static unsigned char iconMaskBits[] = {
  85.    0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  86.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  87.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  88.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  89.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  90.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  91.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  92.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  93.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  94.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  95.    0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f};
  96.  
  97. /*
  98.  * Blank Bitmap
  99.  */
  100.  
  101. #define blankWidth 16
  102. #define blankHeight 16
  103. static unsigned char blankBits[] = {
  104.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  105.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  106.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  107. };
  108.  
  109. /*
  110.  * Private Icon Handling Function Declarations
  111.  */
  112.  
  113. static void    iconClearBitmap(Display*, Window, GC, Pixmap, int, int);
  114. static Pixmap    iconDefaultBitmap(Display*, Window, IconBitmapPart,
  115.             unsigned short*, unsigned short*);
  116. static void    iconFree(IconInfo*);
  117. static Pixmap    iconGetBitmap(Widget, char*, IconBitmapPart, unsigned short*,
  118.             unsigned short*);
  119. static char    *iconGetIconPath(void*, int, IconTyping, IconBitmapPart);
  120. static Pixmap    iconMergeBitmaps(Widget, Pixmap, int, int, Pixmap, int, int,
  121.             int, int, Boolean);
  122.  
  123.  /*************************************************************************
  124.  *
  125.  *    Public Icon Handling Functions
  126.  *
  127.  **************************************************************************/
  128.  
  129. /*
  130.  * IconCreateDouble
  131.  *
  132.  * Create a double icon from a single icon. The double icon has a bitmap
  133.  * consisting of 2 images of the original bitmap offset from one another.
  134.  */
  135. void
  136. IconCreateDouble(
  137.     Widget        widget,
  138.     IconInfo    *oldIcon,
  139.     int        xOffset,
  140.     int        yOffset,
  141.     IconInfo    *newIcon,
  142.     short        xx,
  143.     short        yy)
  144. {
  145.     newIcon->bitmap = iconMergeBitmaps(widget,
  146.         oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height,
  147.         oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height,
  148.         xOffset, yOffset, False);
  149.     newIcon->mask = iconMergeBitmaps(widget,
  150.         oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height,
  151.         oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height,
  152.         xOffset, yOffset, True);
  153.     newIcon->icon.width = oldIcon->icon.width + 10;
  154.     newIcon->icon.height = oldIcon->icon.height + 10;
  155.     newIcon->name = XtNewString("Multiple");
  156.     newIcon->icon.x = xx;
  157.     newIcon->icon.y = yy;
  158.     newIcon->dragIcon = DtDndCreateSourceIcon(widget,
  159.         newIcon->bitmap, newIcon->mask);
  160. }
  161.  
  162. /*
  163.  * IconDelete
  164.  *
  165.  * Remove the icon from its list and deallocate memory used by the icon.
  166.  */
  167. void
  168. IconDelete(
  169.     Widget        drawArea,
  170.     IconInfo    *iconPtr)
  171. {
  172.     IconInfo    *iconList;
  173.  
  174.     if (iconPtr == NULL || drawArea == NULL) {
  175.         return;
  176.     }
  177.  
  178.     if (iconPtr->next != NULL) { /* iconPtr is not the tail of the list */
  179.         iconPtr->next->prev = iconPtr->prev;
  180.     }
  181.  
  182.     if (iconPtr->prev != NULL) { /* iconPtr is not the head of the list */
  183.         iconPtr->prev->next = iconPtr->next;
  184.     }
  185.     if (iconPtr->next == NULL) { /* iconPtr is the tail of the list */
  186.         iconList = iconPtr->prev;
  187.     } else {
  188.         iconList = iconPtr->next;
  189.     }
  190.  
  191.     while (iconList != NULL && iconList->prev != NULL) {
  192.         iconList = iconList->prev;
  193.     }
  194.     iconFree(iconPtr);
  195.  
  196.     XtVaSetValues(drawArea, XmNuserData, iconList, NULL);
  197. }
  198.  
  199. /*
  200.  * IconDraw
  201.  *
  202.  * Render given icon in the window of the given widget.
  203.  */
  204. void
  205. IconDraw(
  206.     Widget        widget,
  207.     IconInfo    *iconPtr)
  208. {
  209.     static GC    graphicsContext = NULL;
  210.     static XFontStruct *fontStruct;
  211.     Display        *display = XtDisplayOfObject(widget);
  212.     Window        window = XtWindow(widget);
  213.     int        screen = DefaultScreen(display);
  214.     XGCValues    gcValues;
  215.  
  216.     if (graphicsContext == NULL) {
  217.         gcValues.foreground = BlackPixel(display, screen);
  218.                 gcValues.background = WhitePixel(display, screen);
  219.                 graphicsContext = XCreateGC(display, window,
  220.                                 GCForeground | GCBackground, &gcValues);
  221.     }
  222.  
  223.     /*
  224.      * Draw icon
  225.      */
  226.  
  227.     gcValues.clip_mask = iconPtr->mask;
  228.     gcValues.clip_x_origin = iconPtr->icon.x;
  229.     gcValues.clip_y_origin = iconPtr->icon.y;
  230.     XChangeGC(display, graphicsContext,
  231.         GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcValues);
  232.     XCopyPlane(display, iconPtr->bitmap, window, graphicsContext, 0, 0,
  233.         iconPtr->icon.width, iconPtr->icon.height,
  234.         iconPtr->icon.x, iconPtr->icon.y, 1L);
  235.  
  236.     /*
  237.      * Draw icon name centered below icon
  238.      */
  239.  
  240.         if (iconPtr->name != NULL) {
  241.                 int             nameX, nameY;
  242.                 int             direction, ascent, decent;
  243.                 XCharStruct     overall;
  244.                 Widget          xmScreen;
  245.  
  246.                 if (fontStruct == NULL) {
  247.                         xmScreen = XmGetXmScreen(XtScreen(widget));
  248.                         XtVaGetValues(xmScreen, XmNfont, &fontStruct, NULL);
  249.                 }
  250.                 XTextExtents(fontStruct, iconPtr->name, strlen(iconPtr->name),
  251.                         &direction, &ascent, &decent, &overall);
  252.  
  253.                 nameX = (iconPtr->icon.x + (iconPtr->icon.width/2)) -
  254.                         (overall.width/2);
  255.                 nameY = iconPtr->icon.y + iconPtr->icon.height +
  256.                         ICON_TEXT_YGAP + ascent;
  257.  
  258.                 gcValues.font = fontStruct->fid;
  259.                 gcValues.clip_mask = None;
  260.                 XChangeGC(display, graphicsContext,
  261.                         GCFont | GCClipMask, &gcValues);
  262.                 XDrawString(display, window, graphicsContext, nameX, nameY,
  263.                         iconPtr->name, strlen(iconPtr->name));
  264.         }
  265. }
  266.  
  267. /*
  268.  * IconInitialize
  269.  *
  270.  * Initialize given icon with given data. Get icon bitmap based on data
  271.  * associated with the icon. This data may be a file name, a buffer or
  272.  * a type name. Create source icon for dragging based on the bitmap and mask.
  273.  */
  274. void
  275. IconInitialize(
  276.     Widget        widget,
  277.     IconInfo    *iconPtr,
  278.     short        x,
  279.     short        y,
  280.     void        *data,
  281.     int        dataLen,
  282.     char        *name,
  283.     IconTyping    typing)
  284. {
  285.     char        *iconPath;
  286.  
  287.     iconPath = iconGetIconPath(data, dataLen, typing, IconMask);
  288.     iconPtr->mask = iconGetBitmap(widget, iconPath, IconMask,
  289.         &(iconPtr->icon.width), &(iconPtr->icon.height));
  290.     XtFree(iconPath);
  291.  
  292.     iconPath = iconGetIconPath(data, dataLen, typing, IconBitmap);
  293.     iconPtr->bitmap = iconGetBitmap(widget, iconPath, IconBitmap,
  294.         &(iconPtr->icon.width), &(iconPtr->icon.height));
  295.     XtFree(iconPath);
  296.  
  297.         iconPtr->icon.x = x;
  298.     iconPtr->icon.y = y;
  299.         iconPtr->name = XtNewString(name);
  300.         iconPtr->dragIcon = DtDndCreateSourceIcon(widget, 
  301.                 iconPtr->bitmap, iconPtr->mask); 
  302. }
  303.  
  304. /*
  305.  * IconNew
  306.  *
  307.  * Allocate memory for a new icon structure and clear.
  308.  */
  309. IconInfo*
  310. IconNew()
  311. {
  312.     IconInfo    *iconPtr;
  313.  
  314.     iconPtr = (IconInfo*) XtMalloc(sizeof(IconInfo));
  315.     memset(iconPtr, 0x00, sizeof(IconInfo));
  316.  
  317.     return iconPtr;
  318. }
  319.  
  320.  /*************************************************************************
  321.  *
  322.  *    Private Icon Handling Functions
  323.  *
  324.  **************************************************************************/
  325.  
  326. /*
  327.  * iconClearBitmap
  328.  *
  329.  * Clear a bitmap by filling it with zeros.
  330.  */
  331. static void
  332. iconClearBitmap(
  333.     Display        *display,
  334.     Window        window,
  335.     GC        graphicsContext,
  336.     Pixmap        bitmap,
  337.     int        width,
  338.     int        height)
  339. {
  340.     int        xx, yy;
  341.     static Pixmap    blankBitmap = NULL;
  342.  
  343.     if (blankBitmap == NULL) {
  344.         blankBitmap = XCreateBitmapFromData(display, window,
  345.             (char *)blankBits, blankWidth, blankHeight);
  346.     }
  347.     for (xx = 0; xx < width + blankWidth; xx += blankWidth) {
  348.             for (yy = 0; yy < height + blankHeight; yy += blankHeight) {
  349.             XCopyArea(display, blankBitmap, bitmap,
  350.                 graphicsContext, 0, 0,
  351.                 blankWidth, blankHeight, xx, yy);
  352.         }
  353.     }
  354. }
  355.  
  356. /*
  357.  * iconDefaultBitmap
  358.  *
  359.  * Create default icon bitmap or mask and set width and height accordingly.
  360.  */
  361. static Pixmap
  362. iconDefaultBitmap(
  363.     Display        *display,
  364.     Window        window,
  365.     IconBitmapPart    iconPart,
  366.     unsigned short    *width,
  367.     unsigned short    *height)
  368. {
  369.     static Pixmap    bitmap;
  370.     static Pixmap    mask;
  371.  
  372.     if (iconPart == IconMask) { /* create default mask */
  373.         if (mask == NULL) {
  374.             mask = XCreateBitmapFromData(display, window,
  375.                (char *)iconMaskBits, iconMaskWidth, iconMaskHeight);
  376.         }
  377.         *width = iconMaskWidth;
  378.         *height = iconMaskHeight;
  379.  
  380.         return mask;
  381.  
  382.     } else { /* create default bitmap */
  383.         if (bitmap == NULL) {
  384.             bitmap = XCreateBitmapFromData(display, window,
  385.                 (char *)iconBits, iconWidth, iconHeight);
  386.         }
  387.         *width = iconWidth;
  388.         *height = iconHeight;
  389.  
  390.         return bitmap;
  391.     }
  392. }
  393.  
  394. /*
  395.  * iconFree
  396.  *
  397.  * Deallocate the icon and associated resources.
  398.  */
  399. static void
  400. iconFree(
  401.     IconInfo    *iconPtr)
  402. {
  403.     Display        *display = XtDisplayOfObject(iconPtr->dragIcon);
  404.  
  405.     if (iconPtr == NULL) {
  406.         return;
  407.     }
  408.  
  409.     XtFree(iconPtr->name);
  410.     /*
  411.      * REMIND: This needs to free other things too...
  412.      * XFreePixmap(display, iconPtr->bitmap);
  413.      * XFreePixmap(display, iconPtr->mask);
  414.      * Free(iconPtr->dragIcon);
  415.      */
  416.     XtFree((char *)iconPtr);
  417. }
  418.  
  419. /*
  420.  * iconGetBitmap
  421.  *
  422.  * Get a bitmap for the icon based on the path and name of the icon. 
  423.  * If no bitmap file is found use a built-in default.
  424.  */
  425. static Pixmap
  426. iconGetBitmap(
  427.     Widget        widget,
  428.     char        *iconPath,
  429.     IconBitmapPart    iconPart,
  430.     unsigned short    *returnWidth,
  431.     unsigned short    *returnHeight)
  432. {
  433.     Display        *display = XtDisplayOfObject(widget);
  434.     Window        window = DefaultRootWindow(display);
  435.     int        status;
  436.     int        xHot, yHot;
  437.     Pixmap        bitmap;
  438.     unsigned int    width, height;
  439.     
  440.     *returnWidth = *returnHeight = 0;
  441.  
  442.     if (iconPath != NULL) {
  443.  
  444.         status = XReadBitmapFile(display, window, iconPath,
  445.             &width, &height, &bitmap, &xHot, &yHot);
  446.  
  447.         if (status == BitmapSuccess) {
  448.             *returnWidth = (unsigned short) width;
  449.             *returnHeight = (unsigned short) height;
  450.         } else {
  451.             printf(
  452.                 "Unable to read icon from bitmap file \"%s\".\n"
  453.                 "Using default icon bitmap.\n",
  454.                 iconPath, NULL);
  455.             bitmap = iconDefaultBitmap(display, window, iconPart,
  456.                 returnWidth, returnHeight);
  457.         }
  458.     } else {
  459.         bitmap = iconDefaultBitmap(display, window, iconPart,
  460.             returnWidth, returnHeight);
  461.     }
  462.     return bitmap;
  463. }
  464.  
  465. /*
  466.  * iconGetIconPath
  467.  *
  468.  * Get the file path and name for an icon based on the given data and
  469.  * method of typing that data. This function assumes the data typing
  470.  * database has been loaded with DtDtsLoadDataTypes().
  471.  */
  472. static char*
  473. iconGetIconPath(
  474.     void        *data,
  475.     int        dataLen,
  476.     IconTyping    typing,
  477.     IconBitmapPart    iconPart)
  478. {
  479.     char        iconPath[MAXPATHLEN + 1],
  480.             *iconName,
  481.             *iconSuffix;
  482.  
  483.     switch (typing) {
  484.     case IconByFile:
  485.         iconName = DtDtsFileToAttributeValue(data, "ICON");
  486.         break;
  487.     case IconByData:
  488.         iconName = DtDtsBufferToAttributeValue(data, dataLen,
  489.             "ICON", NULL);
  490.         break;
  491.     case IconByType:
  492.         iconName = DtDtsDataTypeToAttributeValue(data, "ICON", NULL);
  493.         break;
  494.     default:
  495.         iconName = NULL;
  496.     }
  497.     if (iconName != NULL) {
  498.         if (iconPart == IconMask) {
  499.             iconSuffix = ICON_MASK_SUFFIX;
  500.         } else {
  501.             iconSuffix = ICON_BITMAP_SUFFIX;
  502.         }
  503.         sprintf(iconPath, "%s/%s.%s", ICON_PATH, iconName, iconSuffix);
  504.         DtDtsFreeAttributeValue(iconName);
  505.     }
  506.     return XtNewString(iconPath);
  507. }
  508.  
  509. /*
  510.  * iconMergeBitmaps
  511.  *
  512.  * Create new bitmap consisting of the offset composition of the given bitmaps.
  513.  */
  514. static Pixmap
  515. iconMergeBitmaps(
  516.     Widget        widget,
  517.     Pixmap        bitmap1,
  518.     int        width1,
  519.     int        height1,
  520.     Pixmap        bitmap2,
  521.     int        width2,
  522.     int        height2,
  523.     int        xOffset,
  524.     int        yOffset,
  525.     Boolean        clear)
  526. {
  527.     Display        *display = XtDisplayOfObject(widget);
  528.     Window        window = DefaultRootWindow(display);
  529.     int        screen = DefaultScreen(display);
  530.     Pixmap        mergedBitmap, blankBitmap;
  531.     int        extraX, extraY, width, height;
  532.     static GC    graphicsContext = NULL;
  533.     XGCValues    gcValues;
  534.  
  535.     extraX = width2 - width1 + xOffset + 1;
  536.     if (extraX < 0) extraX = 0;
  537.     width = width1 + extraX;
  538.  
  539.     extraY = height2 - height1 + yOffset + 1;
  540.     if (extraY < 0) extraY = 0;
  541.     height = height1 + extraY;
  542.  
  543.     mergedBitmap = XCreatePixmap(display, window, width, height, 1);
  544.  
  545.     if (graphicsContext == NULL) {
  546.                 graphicsContext = XCreateGC(display, mergedBitmap, 0L, NULL);
  547.     }
  548.  
  549.     if (clear) {
  550.         iconClearBitmap(display, window, graphicsContext, mergedBitmap,
  551.             width, height);
  552.     }
  553.  
  554.     XCopyArea(display, bitmap2, mergedBitmap, graphicsContext, 0, 0,
  555.         width2, height2, xOffset, yOffset);
  556.  
  557.     XCopyArea(display, bitmap1, mergedBitmap, graphicsContext, 0, 0,
  558.         width1, height1, 0, 0);
  559.  
  560.     return mergedBitmap;
  561. }
  562.  
  563.